﻿using System;
using Xunit;
using System.Collections.Generic;
#if NETCore
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
#endif

namespace Longbow.Data
{
    [CollectionDefinition("SQLServerContext")]
    public class SQLServerContext : ICollectionFixture<SQLServerFactory>
    {

    }

    [CollectionDefinition("SQLiteContext")]
    public class SQLiteContext : ICollectionFixture<SQLiteFactory>
    {

    }

    [CollectionDefinition("MySqlContext")]
    public class MySqlContext : ICollectionFixture<MySqlFactory>
    {

    }

    [CollectionDefinition("MariaContext")]
    public class MariaContext : ICollectionFixture<MariaFactory>
    {

    }

    public class DbFactory : IDisposable
    {
#if NETCore
        public IConfiguration Configuration { get; protected set; }
#endif

        public string ConnectionString { get; set; }

        public DatabaseProviderType ProviderName { get; set; }

        public virtual void Dispose()
        {

        }
    }

    public class SQLServerFactory : DbFactory
    {

        public SQLServerFactory()
        {
            ConnectionString = "Data Source=.;Initial Catalog=UnitTest;User ID=sa;Password=sa";
            ProviderName = DatabaseProviderType.SqlServer;

#if NETCore
            Configuration = new ConfigurationBuilder().AddInMemoryCollection(new KeyValuePair<string, string>[] {
                new KeyValuePair<string, string>("ConnectionStrings:ba", ConnectionString),
                new KeyValuePair<string, string>("DB:0:Enabled", "true")
            }).Build();

            var sc = new ServiceCollection();
            sc.AddSingleton(Configuration);
            sc.AddDbAdapter();
#endif

            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("if exists (select * from sys.tables where name = 'Test') drop table Test;CREATE TABLE Test ([ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY, [Name] VARCHAR (50) Not NULL)");
            db.Dispose();
        }

        public override void Dispose()
        {
            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("drop table Test");
            db.Dispose();
        }
    }

    public class SQLiteFactory : DbFactory
    {

        public SQLiteFactory()
        {
            ConnectionString = "Data Source=UnitTest.db";
            ProviderName = DatabaseProviderType.SQLite;

#if NETCore
            Configuration = new ConfigurationBuilder().AddInMemoryCollection(new KeyValuePair<string, string>[] {
                new KeyValuePair<string, string>("ConnectionStrings:ba", ConnectionString),
                new KeyValuePair<string, string>("DB:0:Enabled", "true")
            }).Build();

            var sc = new ServiceCollection();
            sc.AddSingleton(Configuration);
            sc.AddDbAdapter();
#endif

            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("drop table if exists Test;CREATE TABLE Test([ID] INTEGER PRIMARY KEY, [Name] VARCHAR(50) NULL);");
            db.Dispose();
        }

        public override void Dispose()
        {
            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("drop table Test");
            db.Dispose();
        }
    }

    public class MariaFactory : DbFactory
    {

        public MariaFactory()
        {
            ConnectionString = "Server=localhost;Port=4406;Database=test;Uid=root;Pwd=sa;SslMode=none;";
            ProviderName = DatabaseProviderType.SQLite;

#if NETCore
            Configuration = new ConfigurationBuilder().AddInMemoryCollection(new KeyValuePair<string, string>[] {
                new KeyValuePair<string, string>("ConnectionStrings:ba", ConnectionString),
                new KeyValuePair<string, string>("DB:0:Enabled", "true")
            }).Build();

            var sc = new ServiceCollection();
            sc.AddSingleton(Configuration);
            sc.AddDbAdapter();
#endif

            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("drop table if exists Test;CREATE TABLE Test(ID INTEGER PRIMARY KEY Auto_increment, Name VARCHAR(50) NULL);");
            db.Dispose();
        }

        public override void Dispose()
        {
            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("drop table Test");
            db.Dispose();
        }
    }

    public class MySqlFactory : DbFactory
    {

        public MySqlFactory()
        {
            ConnectionString = "Server=localhost;Database=UnitTest;Uid=argozhang;Pwd=argo@163.com;SslMode=none;allowPublicKeyRetrieval=true";
            ProviderName = DatabaseProviderType.MySql;

#if NETCore
            Configuration = new ConfigurationBuilder().AddInMemoryCollection(new KeyValuePair<string, string>[] {
                new KeyValuePair<string, string>("ConnectionStrings:ba", ConnectionString),
                new KeyValuePair<string, string>("DB:0:Enabled", "true")
            }).Build();

            var sc = new ServiceCollection();
            sc.AddSingleton(Configuration);
            sc.AddDbAdapter();
#endif

            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("drop table if exists Test;CREATE TABLE Test(ID INTEGER PRIMARY KEY Auto_increment, Name VARCHAR(50) NULL);");
            db.Dispose();
        }

        public override void Dispose()
        {
            var db = DbManager.Create(new DatabaseOption() { ConnectionString = ConnectionString, ProviderName = ProviderName });
            db.Execute("drop table Test");
            db.Dispose();
        }
    }
}
